package io.renren.modules.project.controller;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import io.renren.common.annotation.SysLog;
import io.renren.common.utils.*;
import io.renren.modules.contract.entity.ContractReceiptEntity;
import io.renren.modules.contract.entity.ContractReceiptExportEntity;
import io.renren.modules.contract.entity.CorporateCheckingEntity;
import io.renren.modules.contract.service.ContractReceiptService;
import io.renren.modules.contract.service.CorporateCheckingService;
import io.renren.modules.oss.constant.UploadConstant;
import io.renren.modules.project.entity.ProjectEnclosureEntity;
import io.renren.modules.project.entity.ProjectExportEntity;
import io.renren.modules.sys.entity.SysUserEntity;
import io.renren.modules.sys.entity.SysUserTokenEntity;
import io.renren.modules.sys.service.SysUserTokenService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import io.renren.modules.project.entity.ProjectEntityEntity;
import io.renren.modules.project.service.ProjectEntityService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static org.springframework.util.StreamUtils.BUFFER_SIZE;


/**
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2018-10-05 18:06:33updateProject
 */
@RestController
@RequestMapping("/generator/projectentity")
public class ProjectEntityController {
    @Autowired
    private ContractReceiptService contractReceiptService;
    @Autowired
    private ProjectEntityService projectEntityService;
    @Autowired
    private SysUserTokenService sysUserTokenService;
    @Autowired
    private CorporateCheckingService corporateCheckingService;

    /**
     * 列表
     */
    @RequestMapping("/list/{userId}/{roleIdList}")
    @RequiresPermissions("generator:projectentity:list")
    public R list(@RequestParam Map<String, Object> params, @PathVariable("userId") String userId, @PathVariable("roleIdList") List<String> roleIdList) {
        //查询列表数据
        Query query = new Query(params);
        List<ProjectEntityEntity> projectEntityList = projectEntityService.queryList(query, userId, roleIdList);
        int total = projectEntityService.queryProjectTotal(query, userId, roleIdList);
        PageUtils pageUtil = new PageUtils(projectEntityList, total, query.getLimit(), query.getPage());

        return R.ok().put("page", pageUtil);
    }

    /**
     * 列表
     */
    @RequestMapping("/queryProject/{userId}")
    public R queryProject(@RequestParam Map<String, Object> params, @PathVariable("userId") String userId) {
        //查询列表数据
        Query query = new Query(params);

        List<ProjectEntityEntity> projectEntityList = projectEntityService.queryProject(query, userId);
        int total = projectEntityService.queryProjectTotalLimt(query, userId);
        PageUtils pageUtil = new PageUtils(projectEntityList, total, query.getLimit(), query.getPage());

        return R.ok().put("page", pageUtil);
    }

    /**
     * 项目经理查看自己项目的附件
     */
    @RequestMapping("/queryEnclosure/{projectId}")
    public R queryEnclosure(@RequestParam Map<String, Object> params, @PathVariable("projectId") String projectId) {
        //查询列表数据
        Query query = new Query(params);
        System.out.println("*****项目名称*****" + projectId);
        //分页查询十条数据
        List<ProjectEnclosureEntity> projectEnclosureList = projectEntityService.queryEnclosure(query, projectId);
        //不分页查询全部数据
        List<ProjectEnclosureEntity> projectEnclosureEntity = projectEntityService.queryEnclosureTotal(query, projectId);
        int total = projectEnclosureEntity.size();
        PageUtils pageUtil = new PageUtils(projectEnclosureList, total, query.getLimit(), query.getPage());
        return R.ok().put("page", pageUtil);
    }

    /**
     * 查询进行中的项目列表
     *
     * @param params
     * @param userId
     * @param roleIdList
     * @return
     */
    @RequestMapping("/doingList/{userId}/{roleIdList}")
    public R doingList(@RequestParam Map<String, Object> params, @PathVariable("userId") String userId, @PathVariable("roleIdList") List<String> roleIdList) {
        //查询列表数据
        Query query = new Query(params);

        List<ProjectEntityEntity> projectEntityList = projectEntityService.queryProjectAttachDoingTaskList(query, userId, roleIdList);
        int total = projectEntityService.queryTotal(query);
        PageUtils pageUtil = new PageUtils(projectEntityList, total, query.getLimit(), query.getPage());

        return R.ok().put("page", pageUtil);
    }

    /**
     * 项目分布统计
     *
     * @param userId
     * @param roleIdList
     * @return
     */
    @RequestMapping("/countProjectStatus/{userId}/{roleIdList}")
    public R countProjectStatus(@PathVariable("userId") String userId, @PathVariable("roleIdList") List<String> roleIdList) {
        Map<String, Object> projectStatus = projectEntityService.countProjectStatus(userId, roleIdList);
        return R.ok().put("projectStatus", projectStatus);
    }

    /**
     * 项目分析
     *
     * @param year
     * @return
     */
    @RequestMapping("/projectAnalysis/{year}")
    public R projectAnalysis(@PathVariable("year") String year) {
        try{
            Map<String,Object> map = projectEntityService.projectAnalysis(year);
            return R.ok().put("data",map);
        }catch (Exception e){
            e.getMessage();
            return R.error("未知异常");
        }
    }


    /**
     * 信息
     */
    @RequestMapping("/info/{id}")
    @RequiresPermissions("generator:projectentity:info")
    public R info(@PathVariable("id") String id) {
        ProjectEntityEntity projectEntity = projectEntityService.queryObject(id);

        return R.ok().put("projectEntity", projectEntity);
    }

    /**
     * 查询项目信息
     *
     * @param id
     * @return
     */
    @RequestMapping("/queryInfo/{id}")
    @RequiresPermissions("generator:projectentity:info")
    public R queryInfo(@PathVariable("id") String id) {
        ProjectEntityEntity projectEntity = projectEntityService.queryInfoObject(id);
        CorporateCheckingEntity corporateCheckingEntity = corporateCheckingService.queryMoney(projectEntity.getId());
        if (corporateCheckingEntity != null && corporateCheckingEntity.getCorporateCheckingMoney() != null){
            projectEntity.setCorporateCheckingMoney(corporateCheckingEntity.getCorporateCheckingMoney());
        }
        return R.ok().put("projectEntity", projectEntity);
    }

    /**
     * 保存
     */
    @SysLog("创建项目")
    @RequestMapping("/save")
    @RequiresPermissions("generator:projectentity:save")
    public R save(@RequestBody ProjectEntityEntity projectEntity) {
        String projectId = RandomId.createId() + "";
        projectEntity.setId(projectId);
        String isOk = projectEntityService.save(projectEntity);
        Map<String, Object> map = new HashMap<>();
        if ("该项目编号已存在".equals(isOk)) {
            map.put("msg", "0101");
        } else {
            map.put("projectId", projectId);
            map.put("projectName", projectEntity.getProjectName());
        }
        return R.ok(map);
    }

    /**
     * 修改
     */
    @SysLog("项目终止")
    @RequestMapping("/update")
    public R update(@RequestBody ProjectEntityEntity projectEntity) {
        projectEntityService.update(projectEntity);
        return R.ok();
    }

    /**
     * 删除 "所有项目列表"菜单的del删除/rec恢复/tre终止按钮  做逻辑删除
     */
    @SysLog("改变项目状态，del删除/rec恢复/tre终止")
    @RequestMapping("/delete/{cord}")
    @RequiresPermissions("generator:projectentity:delete")
    public R delete(@RequestBody String[] ids, @PathVariable("cord") String cord) {
        projectEntityService.deleteBatch(ids, cord);

        return R.ok();
    }

    /**
     * 修改项目信息
     */
    @RequestMapping("/updateProject")
    public R updateProject(@RequestBody ProjectEntityEntity projectEntity) {
        if (projectEntity.getCorporateCheckingMoney() != null){
            CorporateCheckingEntity corporateCheckingEntity = corporateCheckingService.queryMoney(projectEntity.getId());
            if (corporateCheckingEntity != null && corporateCheckingEntity.getCorporateCheckingMoney() != null){
                  corporateCheckingEntity.setCorporateCheckingMoney(projectEntity.getCorporateCheckingMoney());
                  corporateCheckingService.update(corporateCheckingEntity);
            }else {
                CorporateCheckingEntity checkingEntity = new CorporateCheckingEntity();
                checkingEntity.setCorporateCheckingMoney(projectEntity.getCorporateCheckingMoney());
                checkingEntity.setProjectId(projectEntity.getId());
                corporateCheckingService.save(checkingEntity);
            }
        }
        projectEntityService.update(projectEntity);
        return R.ok();
    }

    //创建项目调整之后保存
    @RequestMapping("/taskPreservation")
    public R taskPreservation(@RequestBody ProjectEntityEntity projectEntity) {
        String projectId = projectEntity.getId();
        projectEntityService.taskPreservation(projectId);
        return R.ok();
    }

    //打包下载附件
    @RequestMapping("/downloadFile")
    public R downloadFile(@RequestBody String projectId, HttpServletRequest request) {
        try {
            System.out.println(projectId);
            //去掉双引号
            if (!"".equals(projectId)) {
                projectId = projectId.replace("\"", "");
            }
            Map<String, Object> map = new HashMap<>();
            List<ProjectEnclosureEntity> projectEnclosureList = projectEntityService.queryEnclosureTotal(map, projectId);
            System.out.println(projectEnclosureList.size());
            if (projectEnclosureList.size() > 0 && projectEnclosureList != null) {
                String[] fliePath = new String[projectEnclosureList.size()];
                for (int i = 0; i < projectEnclosureList.size(); i++) {
                    fliePath[i] = projectEnclosureList.get(i).getEnclosurePath();
                }
                System.out.println(fliePath.length);
                List<File> fileList = new ArrayList<>();
                for (int i = 0; i < fliePath.length; i++) {
                    fileList.add(new File(fliePath[i]));
                }
                long date = new Date().getTime();
                String fileZipPath = "E:/qgb/zip/" + projectEnclosureList.get(0).getProjectName() + date + ".zip";
                String fileZipName = projectEnclosureList.get(0).getProjectName() + date + ".zip";
                FileOutputStream fos2 = new FileOutputStream(new File(fileZipPath));
                this.toZip(fileList, fos2);
                String getContextPath = request.getContextPath();
                String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + getContextPath + "/";
                String baseUrl = basePath + UploadConstant.ZIP_FILE + "/";
                SysUserEntity user = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
                SysUserTokenEntity userToken = sysUserTokenService.queryByUserId(user.getUserId());
                String imageUrl = baseUrl  +fileZipName + "?token=" + userToken.getToken();
                System.out.println("*****baseUrl******:" + baseUrl);
                System.out.println("*****imageUrl*****"+imageUrl);
                Map<String, Object> returnMap = new HashMap<>();
                returnMap.put("imageUrl",imageUrl);
                return R.ok(returnMap);
            }
        } catch (Exception e) {
            e.getMessage();
        }
        //  System.out.println(fliePath.length);
        return R.error("下载失败");
    }

    /**
     * 压缩成ZIP
     *
     * @param srcFiles 需要压缩的文件列表
     * @param out      压缩文件输出流
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    public static void toZip(List<File> srcFiles, OutputStream out) throws RuntimeException {
        long start = System.currentTimeMillis();
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(out);
            for (File srcFile : srcFiles) {
                byte[] buf = new byte[BUFFER_SIZE];
                zos.putNextEntry(new ZipEntry(srcFile.getName()));
                int len;
                FileInputStream in = new FileInputStream(srcFile);
                while ((len = in.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                in.close();
            }
            long end = System.currentTimeMillis();
            System.out.println("压缩完成，耗时：" + (end - start) + " ms");
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils", e);
        } finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 收付款统计列表
     */
    @RequestMapping("/receivingStatistics/{userId}/{roleIdList}")
    public R receivingStatistics(@RequestParam Map<String, Object> params, @PathVariable("userId") String userId, @PathVariable("roleIdList") List<String> roleIdList) {
        //查询列表数据
        Query query = new Query(params);
        List<ProjectEntityEntity> projectEntityList = projectEntityService.receivingStatistics(query, userId, roleIdList);
        int total = projectEntityService.receivingStatisticsTotal(query, userId, roleIdList);
        PageUtils pageUtil = new PageUtils(projectEntityList, total, query.getLimit(), query.getPage());

        return R.ok().put("page", pageUtil);
    }

    /**
     *项目信息导出
     */
    @RequestMapping("/exportXls/{userId}/{roleIdList}")
    public R exportXls(@RequestParam Map<String, Object> params,
                          @PathVariable("userId") String userId,
                          @PathVariable("roleIdList") List<String> roleIdList,HttpServletResponse response) {

        //查询导出数据
        List<ProjectExportEntity> projectExportEntities = projectEntityService.projectExport(params, userId, roleIdList);
        //生成文件
        try (OutputStream out = response.getOutputStream()) {
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename="
                    + new String("项目列表导出.xlsx".getBytes("GB2312"), "ISO_8859_1"));
            ExcelWriter writer = EasyExcelFactory.getWriter(out);
            Sheet sheet = new Sheet(1, 0, ProjectExportEntity.class);
            writer.write(projectExportEntities, sheet);
            writer.finish();
        } catch (Exception e) {
        }
        return R.ok();
    }

    /**
     *收付款信息导出
     */
    @RequestMapping("/receivingExportXls/{userId}/{roleIdList}")
    public R receivingExportXls(@RequestParam Map<String, Object> params,
                       @PathVariable("userId") String userId,
                       @PathVariable("roleIdList") List<String> roleIdList,HttpServletResponse response) {
        // 所有行的集合
        List<List<Object>> list = new ArrayList<List<Object>>();
        int i = 0;//记录项目下最大合同数
        //List<String> contractNames = new ArrayList<>();

        //查询项目信息
        List<ProjectExportEntity> projectExportEntities = projectEntityService.projectExport(params, userId, roleIdList);
        //遍历项目信息,查询项目下的合同信息
        for (ProjectExportEntity p :projectExportEntities) {
            //查询项目下所有的合同信息，并添加到项目信息中
            List<Object> sbValue = new ArrayList<>();
            String[] fieldNames = getFiledName(p);

            //遍历项目信息的值，存入数组
            for(int j=0 ; j<fieldNames.length ; j++){     //遍历所有属性
                String name = fieldNames[j];    //获取属性的名字
                if (!name.equals("id")){
                    Object value = new Object();
                    value = getFieldValueByName(name,p);
                    sbValue.add(value);
                }
            }
            //循环项目下的合同
            List<ContractReceiptExportEntity> contractReceiptExportEntities = contractReceiptService.getContractReceiptAll(p.getId());

            //如果该项目下的合同数大于记录的最大值，则更新
            if (i<contractReceiptExportEntities.size()){
                i=contractReceiptExportEntities.size();

                //如果合同总数大于记录，清空之前保存的合同名称
                //contractNames.clear();
            }

            for (ContractReceiptExportEntity c :contractReceiptExportEntities) {
                //保存合同名称
                //contractNames.add(c.getContractName());

                String[] receiptNames = getFiledName(c);
                //遍历合同所有值，存入数组
                for(int j=0 ; j<receiptNames.length ; j++){     //遍历所有属性
                    String name = receiptNames[j];    //获取属性的名字
                    if (!name.equals("id")){
                        Object value1 = new Object();
                        value1 = getFieldValueByName(name,c);
                        sbValue.add(value1);
                    }
                }
            }
            //一行数据拼接完成，插入list
            list.add(sbValue);
        }

        // 动态添加 表头 headList --> 所有表头行集合
        List<List<String>> headList = new ArrayList<List<String>>();
        // 项目信息部分表头写死
        List<String> headTitle0 = new ArrayList<String>();
        List<String> headTitle1 = new ArrayList<String>();
        List<String> headTitle2 = new ArrayList<String>();
        List<String> headTitle3 = new ArrayList<String>();
        List<String> headTitle4 = new ArrayList<String>();
        List<String> headTitle5 = new ArrayList<String>();
        List<String> headTitle6 = new ArrayList<String>();
        List<String> headTitle7 = new ArrayList<String>();
        List<String> headTitle8 = new ArrayList<String>();
        List<String> headTitle9 = new ArrayList<String>();
        List<String> headTitle10 = new ArrayList<String>();
        List<String> headTitle11 = new ArrayList<String>();
        List<String> headTitle12 = new ArrayList<String>();
        List<String> headTitle13 = new ArrayList<String>();
        List<String> headTitle14 = new ArrayList<String>();
        List<String> headTitle15 = new ArrayList<String>();
        List<String> headTitle16 = new ArrayList<String>();
        List<String> headTitle17 = new ArrayList<String>();
        headTitle0.add("项目信息");
        headTitle0.add("项目名");
        headTitle1.add("项目信息");
        headTitle1.add("项目编号");
        headTitle2.add("项目信息");
        headTitle2.add("状态");
        headTitle3.add("项目信息");
        headTitle3.add("当前任务");
        headTitle4.add("项目信息");
        headTitle4.add("当前任务責任人");
        headTitle5.add("项目信息");
        headTitle5.add("当前任务状态");
        headTitle6.add("项目信息");
        headTitle6.add("电压类型");
        headTitle7.add("项目信息");
        headTitle7.add("相关线路");
        headTitle8.add("项目信息");
        headTitle8.add("项目经理");
        headTitle9.add("项目信息");
        headTitle9.add("项目开始时间");
        headTitle10.add("项目信息");
        headTitle10.add("申报时间");
        headTitle11.add("项目信息");
        headTitle11.add("项目描述");
        headTitle12.add("项目信息");
        headTitle12.add("实际开始时间");
        headTitle13.add("项目信息");
        headTitle13.add("实际结束时间");
        headTitle14.add("项目信息");
        headTitle14.add("法人管理费");
        headTitle15.add("项目信息");
        headTitle15.add("收款金额");
        headTitle16.add("项目信息");
        headTitle16.add("付款金额");
        headTitle17.add("项目信息");
        headTitle17.add("收付款比例");

        headList.add(headTitle0);
        headList.add(headTitle1);
        headList.add(headTitle2);
        headList.add(headTitle3);
        headList.add(headTitle4);
        headList.add(headTitle5);
        headList.add(headTitle6);
        headList.add(headTitle7);
        headList.add(headTitle8);
        headList.add(headTitle9);
        headList.add(headTitle10);
        headList.add(headTitle11);
        headList.add(headTitle12);
        headList.add(headTitle13);
        headList.add(headTitle14);
        headList.add(headTitle15);
        headList.add(headTitle16);
        headList.add(headTitle17);

        //动态生成合同表头
        for (int a = 0; a < i; a++){
            List<String> headTitleA = new ArrayList<String>();
            List<String> headTitleB = new ArrayList<String>();
            List<String> headTitleC = new ArrayList<String>();
            List<String> headTitleD = new ArrayList<String>();
            List<String> headTitleE = new ArrayList<String>();
            List<String> headTitleF = new ArrayList<String>();
            List<String> headTitleG = new ArrayList<String>();
            /*List<String> headTitleH = new ArrayList<String>();
            List<String> headTitleI = new ArrayList<String>();
            List<String> headTitleJ = new ArrayList<String>();*/
            headTitleA.add("合同信息");
            headTitleA.add("合同名称");
            headTitleB.add("合同信息");
            headTitleB.add("报装单位");
            headTitleC.add("合同信息");
            headTitleC.add("合同金额");
            headTitleD.add("合同信息");
            headTitleD.add("决算金额");
            headTitleE.add("合同信息");
            headTitleE.add("招标批次");
            headTitleF.add("合同信息");
            headTitleF.add("已收款金额");
            headTitleG.add("合同信息");
            headTitleG.add("付款总金额");
            /*headTitleH.add("合同信息");
            headTitleH.add("收款比例");
            headTitleI.add("合同信息");
            headTitleI.add("付款比例");
            headTitleJ.add("合同信息");
            headTitleJ.add("已收款占比");*/

            headList.add(headTitleA);
            headList.add(headTitleB);
            headList.add(headTitleC);
            headList.add(headTitleD);
            headList.add(headTitleE);
            headList.add(headTitleF);
            headList.add(headTitleG);
            /*headList.add(headTitleH);
            headList.add(headTitleI);
            headList.add(headTitleJ);*/
        }

        try (OutputStream out = response.getOutputStream()){
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename="
                    + new String("收付款统计导出.xlsx".getBytes("GB2312"), "ISO_8859_1"));
            ExcelWriter writer = EasyExcelFactory.getWriter(out);
            // 表单
            Sheet sheet = new Sheet(1,0);
            sheet.setSheetName("sheet1");
            // 创建一个表格
            Table table = new Table(1);
            table.setHead(headList);

            writer.write1(list,sheet,table);
            // 记得 释放资源
            writer.finish();
            System.out.println("ok");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.ok();
    }

    /**
     * 获取属性名数组
     * */
    private static String[] getFiledName(Object o){
        Field[] fields=o.getClass().getDeclaredFields();
        String[] fieldNames=new String[fields.length];
        for(int i=0;i<fields.length;i++){
//            System.out.println(fields[i].getType());
            fieldNames[i]=fields[i].getName();
        }
        return fieldNames;
    }

    /**
     * 根据属性名获取属性值
     * */
    private static Object getFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[] {});
            Object value = method.invoke(o, new Object[] {});
            return value;
        } catch (Exception e) {

            return null;
        }
    }

}
